home *** CD-ROM | disk | FTP | other *** search
- /*
- HEADER: CUGXXX;
- TITLE: Mathematical subroutines;
- DATE: 3-20-86;
- DESCRIPTION: Mathematical subroutines;
- KEYWORDS: Mathematics, Math functions;
- FILENAME: MATHMAX.C;
- WARNINGS: None;
- AUTHORS: Max R. Dürsteler;
- COMPILER: Lattice C, Microsoft C;
- REFERENCES: US-DISK 1307;
- ENDREF
- */
-
- /*****************************************************************************
- * *
- * MATH.C Mathematical subroutines for use with Lattice or Microsoft- *
- * compiler. *
- * By Max R. Dürsteler, 12405 Village Sq. Terrace, Rockville MD *
- * *
- *****************************************************************************
- */
-
- /* SQRT.C
- * Calculates square root
- * Precision: 11.05 E-10
- * Range: 0 to e308
- * Author: Max R. Dürsteler
- */
- double sqrt(x)
- double x;
- {
- typedef union { /* Makes use of internal data */
- double d; /* representation */
- unsigned u[4];
- } DBL;
- double y, re, p, q;
- unsigned ex; /* exponens*/
- DBL *xp;
-
- xp = (DBL *)&x;
- ex = xp->u[3] & ~0100017; /* save exponens */
- re = ex & 020 ? 1.4142135623730950488 : 1.0;
- ex = ex - 037740 >> 1;
- ex &= ~0100017;
- xp->u[3] &= ~0177760; /* erase exponens and sign*/
- xp->u[3] |= 037740; /* arrange for mantissa in range 0.5 to 1.0 */
- if (xp->d < .7071067812) { /* multiply by sqrt(2) if mantissa < 0.7 */
- xp->d *= 1.4142135623730950488;
- if (re > 1.0) re = 1.189207115002721;
- else re = 1.0 / 1.18920711500271;
- }
- p = .54525387389085 + /* Polynomial approximation */
- xp->d * (13.65944682358639 + /* from: COMPUTER APPROXIMATIONS*/
- xp->d * (27.090122712655 + /* Hart, J.F. et al. 1968 */
- xp->d * 6.43107724139784));
- q = 4.17003771413707 +
- xp->d * (24.84175210765124 +
- xp->d * (17.71411083016702 +
- xp->d ));
- xp->d = p / q;
- xp->u[3] = xp->u[3] + ex & ~0100000;
- xp->d *= re;
- return(xp->d);
- }
-
-
- /* EXP2.C
- * Calculates exponens to base 2 using polynomial approximations
- * Precision: 10E-10
- * Range:
- * Author: Max R. Dürsteler
- */
- double exp2(x)
- double x;
- {
- typedef union {
- double d;
- unsigned u[4];
- } DBL;
- double y, x2, p, q, re;
- int ix;
- DBL *xp, *yp;
-
- xp = (DBL *)&x;
- y = 0.0;
- yp = (DBL *)&y;
- if(xp->d > 1023.0 || xp->d < -1023.0) return (1E307);
- ix = (int) xp->d;
- yp->u[3] += ix + 1023 << 4;
- yp->u[3] &= ~0100017;
- if ((xp->d -= (double) ix) == 0.0) return(yp->d);
- if (xp->d < 0.0) {
- yp->u[3] -= 1 << 4;
- yp->u[3] &= ~0100017;
- xp->d++;
- }
- if (xp->d >= 0.5) { /* adjust to range 0-0.5 */
- xp->d -= 0.5;
- re = 1.41421356237309504880;
- }
- else re = 1.0;
- x2 = xp->d * xp->d;
- p = xp->d * (7.2152891511493 +
- x2 * 0.0576900723731);
- q = 20.8189237930062 +
- x2 ;
- xp->d = (q + p) / (q - p);
- yp->d *= re * xp->d;
- return(yp->d);
- }
-
-
- /* POW.C
- * Calculates y^x
- * Precision:
- * Range: o to big for y, +/-1023 for x
- * Author: Max R. Dürsteler, 10/2/83
- */
-
- double pow(y,x)
- double y, x;
- {
- typedef union {
- double d;
- unsigned u[4];
- } DBL;
- double z, w, p, p2, q, re;
- unsigned ex; /* exponens*/
- int iz;
- DBL *yp, *zp, *wp;
-
- yp = (DBL *)&y;
- if (yp->d <= 0.0) y = -y;
- z = 0.0;
- zp = (DBL *)&z;
- zp->u[3] = yp->u[3] & ~0100017; /* save exponens */
- iz = (zp->u[3] >> 4)-1023;
- if ((yp->d - zp->d) == 0.0)
- z = (double)iz;
- else {
- yp->u[3] -= ++iz << 4; /* arrange for range 0.5 to 0.99999999999 */
- yp->d *= 1.4142135623730950488; /* shift for 1/sqrt(2) to sqrt(2) */
- p = (yp->d - 1.0) / (yp->d + 1.0);
- p2 = p * p;
- z = p * (2.000000000046727 + /* Polynomial approximation */
- p2 * (0.666666635059382 + /* from: COMPUTER APPROXIMATIONS*/
- p2 * (0.4000059794795 + /* Hart, J.F. et al. 1968 */
- p2 * (0.28525381498 +
- p2 * 0.2376245609 ))));
- z = z * 1.442695040888634 + (double)iz - 0.5;
- }
- z *= x;
- w = 0.0;
- wp = (DBL *)&w;
- if(zp->d > 1023.0 || zp->d < -1023.0) return (1E307);
- iz = (int) zp->d;
- wp->u[3] += iz + 1023 << 4;
- wp->u[3] &= ~0100017;
- if ((zp->d -= (double) iz) == 0.0) return(wp->d);
- while (zp->d < 0.0) {
- wp->u[3] -= 1 << 4;
- wp->u[3] &= ~0100017;
- zp->d++;
- }
- if (zp->d >= 0.5) { /* adjust to range 0-0.5 */
- zp->d -= 0.5;
- re = 1.41421356237309504880;
- }
- else re = 1.0;
- p2 = zp->d * zp->d;
- p = zp->d * (7.2152891511493 +
- p2 * 0.0576900723731);
- q = 20.8189237930062 +
- p2 ;
- zp->d = re * wp->d * (q + p) / (q - p);
- return(zp->d);
- }
-
-
- /* FMOD.C
- * Returns the number f such that x = i*y + f. i is an integer, and
- * 0 <= f < y.
- */
- double fmod(x, y)
- double x, y;
- {
- double zint, z;
- int i;
-
- z = x / y;
- zint = 0.0;
- while (z > 32768.0) {
- zint += 32768.0;
- z -= 32768;
- }
- while (z < -32768.0) {
- zint -= 32768.0;
- z += 32768.0;
- }
- i = (int) z;
- zint += (double) i;
- return( x - zint * y);
- }
-
- /*ASIN.C
- *Calculates arcsin(x)
- *Range: 0 <= x <= 1
- *Precision: +/- .000,000,02
- *Header: math.h
- *Author: Max R. Dürsteler
- */
- extern double sqrt();
-
- double asin(x)
- double x;
-
- {
- double y;
- int sign;
-
- if (x > 1.0 || x < -1.0) exit(1);
- sign = 0;
- if (x < 0) {
- sign = 1;
- x = -x;
- }
- y = ((((((-.0012624911 * x
- + .0066700901) * x
- - .0170881256) * x
- + .0308918810) * x
- - .0501743046) * x
- + .0889789874) * x
- - .2145988016) * x
- +1.5707963050;
- y = 1.57079632679 - sqrt(1.0 - x) * y;
- if (sign) y = -y;
- return(y);
- }
-
- /* SIN.C
- * Calculates sin(x), angle x must be in rad.
- * Range: -pi/2 <= x <= pi/2
- * Precision: +/- .000,000,005
- * Header: math.h
- * Author: Max R. Dürsteler
- */
-
- double sin(x)
- double x;
- {
- double xi, y, q, q2;
- int sign;
-
- xi = x; sign = 1;
- while (xi < -1.57079632679489661923) xi += 6.28318530717958647692;
- while (xi > 4.71238898038468985769) xi -= 6.28318530717958647692;
- if (xi > 1.57079632679489661923) {
- xi -= 3.141592653589793238462643;
- sign = -1;
- }
- q = xi / 1.57079632679; q2 = q * q;
- y = ((((.00015148419 * q2
- - .00467376557) * q2
- + .07968967928) * q2
- - .64596371106) * q2
- +1.57079631847) * q;
- return(sign < 0? -y : y);
- }
-
-
- /* LOG.C
- * Calculates natural logarithmus
- * Precision: 11.56 E-10
- * Range: 0 to e308
- * Author: Max R. Dürsteler
- */
- double log(x)
- double x;
- {
- typedef union {
- double d;
- unsigned u[4];
- } DBL;
- double y, z, z2, p;
- unsigned ex; /* exponens*/
- int ix;
- DBL *xp, *yp;
-
- xp = (DBL *)&x;
- if (xp->d <= 0.0) return(y);
- y = 0.0;
- yp = (DBL *)&y;
- yp->u[3] = xp->u[3] & ~0100017; /* save exponens */
- ix = (yp->u[3] >> 4)-1023;
- if ((xp->d - yp->d) == 0.0) return( .693147180559945 * (double)ix);
- xp->u[3] -= ++ix << 4; /* arrange for range 0.5 to 0.99999999999 */
- xp->d *= 1.4142135623730950488; /* shift for 1/sqrt(2) to sqrt(2) */
- z = (xp->d - 1.0) / (xp->d + 1.0);
- z2 = z * z;
- y = z * (2.000000000046727 + /* Polynomial approximation */
- z2 * (0.666666635059382 + /* from: COMPUTER APPROXIMATIONS*/
- z2 * (0.4000059794795 + /* Hart, J.F. et al. 1968 */
- z2 * (0.28525381498 +
- z2 * 0.2376245609 ))));
- y = y + .693147180559945 * ((double)ix - 0.5);
- return(yp->d);
- }
-
- /* ATAN.C
- * Calculates arctan(x)
- * Range: -infinite <= x <= infinite (Output -pi/2 to +pi/2)
- * Precision: +/- .000,000,04
- * Header: math.h
- * Author: Max R. Dürsteler 9/15/83
- */
-
- double atan(x)
- double x;
- {
- double xi, q, q2, y;
- int sign;
-
- xi = (x < 0. ? -x : x);
- q = (xi - 1.0) / (xi + 1.0); q2 = q * q;
- y = ((((((( - .0040540580 * q2
- + .0218612286) * q2
- - .0559098861) * q2
- + .0964200441) * q2
- - .1390853351) * q2
- + .1994653599) * q2
- - .3332985605) * q2
- + .9999993329) * q + 0.785398163397;
- return(x < 0. ? -y: y);
- }
-
-
- /* FLOOR.C
- * Returns largest integer not greater than x
- * Author: Max R. Dürsteler 9/26/83
- */
- double floor(x)
- double x;
- {
- double y;
- int ix;
-
- y = 0.0;
- while (x >= 32768.0) {
- y += 32768.0;
- x -= 32768.0;
- }
- while (x <= -32768.0) {
- y -= 32768.0;
- x += 32768.0;
- }
- if (x > 0.0) ix = (int) x;
- else ix = (int)(x - 0.9999999999);
- return( y + (double) ix);
- }
-
-
- /* CEIL.C
- * Returns smallest integer not less than x
- * Author: Max R. Dürsteler 9/26/83
- */
- double ceil(x)
- double x;
- {
- double y;
- int ix;
-
- y = 0.0;
- while (x >= 32768.0) {
- y += 32768.0;
- x -= 32768.0;
- }
- while (x <= -32768.0) {
- y -= 32768.0;
- x += 32768.0;
- }
- if (x > 0.0) ix = (int) (x + 0.999999999999999);
- else ix = (int) x;
- return( y + (double) ix);
- }
-
- /* EXP.C
- * Calculates exponens of x to base e
- * Range: +/- exp(88)
- * Precision: +/- .000,000,000,1
- * Author: Max R. Dürsteler, 9/20/83
- */
- double exp(xi)
- double xi;
- {
- double y, ex, px, nn, ds, in;
-
- if (xi > 88.0) return(1.7014117331926443e38);
- if (xi < -88.0) return(0.0);
- ex = 1.0;
- while( xi > 1.0) {
- ex *= 2.718281828459; /* const. e */
- xi--;
- }
- while( xi < -1.0) {
- ex *= .367879441171; /* 1/e */
- xi++;
- }
- /* Slow, but more precise Taylor expansion series */
- y = ds = 1.0; nn = 0.0;
- while ((ds < 0.0 ? -ds : ds) > 0.000000000001) {
- px = xi/++nn; /* above precision required */
- ds *= px;
- y += ds;
- }
- y *= ex;
-
- /* Chebyshev polynomials: fast, but less precise then expected!
- * xi = -xi;
- * y = (((((.0000006906 * xi
- * +.0000054302) * xi
- * +.0001715620) * xi
- * +.0025913712) * xi
- * +.0312575832) * xi
- * +.2499986842) * xi
- * +1.0;
- * y = ex / (y * y * y * y);
- */
- return(y);
- }
-
-
- /* LOG10.C
- * Approximation for logarithm of basis 10
- * Range 0 < x < 1e+38
- * Precision: +/- 0.000,000,1
- * Header: math.h
- * Author: Max R. Dürsteler 9/15/83
- */
-
- /* Method of Chebyshev polynomials */
- /* C. Hastings, jr. 1955 */
-
- double log10(x)
- double x;
- {
- double xi, y, q, q2;
- int ex;
-
- if (x <= 0.0) return(0.); /* Error!! */
- ex = 0.0; xi = x;
- while (xi < 1.0 ) {
- xi *= 10.0;
- ex--;
- }
- while (xi > 10.0) {
- xi *= 0.1;
- ex++;
- }
- q = (xi - 3.16227766) / (xi + 3.16227766); q2 = q * q;
- y = ((((.191337714 * q2
- + .094376476) * q2
- + .177522071) * q2
- + .289335524) * q2
- + .868591718) * q + .5;
- y += (double) ex;
- return(y);
- }
-
- /* PW10.C
- * Calculates 10 power x
- * Range: 0 <= x <= 1
- * Precision: +/- 0.000,000,005
- * Header: math.lib
- * Author: Max R. Dürsteler 9/15/83
- */
-
- double pw10(x)
- double x;
- {
- double xi,ex,y;
-
- if (x > 38.0) return(1.7014117331926443e38);
- if (x < -38.0) return(0.0);
- xi = x; ex = 1.0;
- while (xi > 1.0) {
- ex *= 10.0;
- xi--;
- }
- while (xi < 0.0) {
- ex *= 0.1;
- xi++;
- }
- y = ((((((.00093264267 * xi
- + .00255491796) * xi
- + .01742111988) * xi
- + .07295173666) * xi
- + .25439357484) * xi
- + .66273088429) * xi
- +1.15129277603) * xi + 1.0;
- y *= y;
- return(y*ex);
- }
-